package com.molichuxing.services.business.service.impl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import com.molichuxing.framework.dto.TabDto;
import com.molichuxing.services.business.dto.request.modify.ReportModifyBizDto;
import com.molichuxing.services.infrastructure.dto.request.create.CheckCreateDto;
import com.molichuxing.services.infrastructure.dto.request.create.CheckDisputeCreateDto;
import com.molichuxing.services.infrastructure.dto.request.modify.CheckDisputeModifyDto;
import com.molichuxing.services.property.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.molichuxing.framework.dto.Paged;
import com.molichuxing.framework.exception.BizException;
import com.molichuxing.services.business.convertor.Convert;
import com.molichuxing.services.business.dto.response.CarCheckDto;
import com.molichuxing.services.business.dto.response.PdiCheckBizDto;
import com.molichuxing.services.business.service.CarCheckBizService;
import com.molichuxing.services.exception.VehicleExceptionCodeEnum;
import com.molichuxing.services.infrastructure.dto.request.modify.CheckModifyDto;
import com.molichuxing.services.infrastructure.dto.request.modify.DisPdiCheckModifyDto;
import com.molichuxing.services.infrastructure.dto.request.modify.PdiCheckModifyDto;
import com.molichuxing.services.infrastructure.dto.response.CarDto;
import com.molichuxing.services.infrastructure.dto.response.CheckDisputeDto;
import com.molichuxing.services.infrastructure.dto.response.CheckDto;
import com.molichuxing.services.infrastructure.dto.response.CheckImageDto;
import com.molichuxing.services.infrastructure.service.CarService;
import com.molichuxing.services.infrastructure.service.CheckDisputeService;
import com.molichuxing.services.infrastructure.service.CheckImageService;
import com.molichuxing.services.infrastructure.service.CheckPreparationService;
import com.molichuxing.services.infrastructure.service.CheckService;

/**
 * <p>
 * 车辆检验列表服务实现类
 * </p>
 *
 */
@Service("carCheckBizService")
public class CarCheckBizServiceImpl implements CarCheckBizService {
	private static final Logger logger = LoggerFactory.getLogger(CarCheckBizServiceImpl.class);

	@Resource
	private CarService carService;

	@Resource
	private CheckService checkService;

	@Resource
	private CheckImageService checkImageService;

	@Resource
	private CheckDisputeService checkDisputeService;

	@Resource
	private CheckPreparationService checkPreparationService;

	@Override
	public Paged<CarCheckDto> getCarCheck(String licencePlate, String vin, CarsTypeEnum carsTypeEnum,
			CarCheckStatusEnum carCheckStatusEnum, LocalDateTime startCheckTime, LocalDateTime endCheckTime,
			Integer pageSize, Integer pageNum) {
		Paged<CarCheckDto> dtoList = new Paged<CarCheckDto>();
		dtoList.setTab(getTabList());

		List<Integer> carIds = new ArrayList<>();
		CarDto catDto;
		if (licencePlate != null || vin != null) {
			catDto = carService.getByVinLicencePlate(vin, licencePlate);
			if (catDto != null) {
				carIds.add(catDto.getId());
			} else {
				return dtoList;
			}
		}

		// 检验表基础信息
		Paged<CheckDto> list = checkService.getCarsCheckListPage(carIds, carsTypeEnum, carCheckStatusEnum,
				startCheckTime, endCheckTime, pageSize, pageNum);
		if (list == null) {
			return dtoList;
		}
		list.setTab(dtoList.getTab());
		List<CheckDto> checkDtoList = list.getList();
		if (checkDtoList == null) {
			return dtoList;
		}

		dtoList = Convert.toPagedCarCheckDto(list);



		// 遍历检验的基础信息
		for (int i=0;i< dtoList.getList().size();i++) {
			CarDto carDto = carService.getCarById(dtoList.getList().get(i).getCarId());
			dtoList.getList().get(i).setCarId(carDto.getId());
			dtoList.getList().get(i).setLicencePlate(carDto.getLicencePlate());
			dtoList.getList().get(i).setVin(carDto.getVin());
			dtoList.getList().get(i).setVehicleId(carDto.getVehicleId());
			dtoList.getList().get(i).setStatusStr(CarCheckStatusEnum.getName(Integer.valueOf(dtoList.getList().get(i).getStatus())));
            dtoList.getList().get(i).setCarTypeStr(CarsTypeEnum.getName(dtoList.getList().get(i).getCarType()));
		}
		return dtoList;
	}

	@Override
	public List<CarCheckDto> getCheckByCarId(Integer carId) {
		List<CarCheckDto> result = Convert.toCarCheckDto(checkService.getCheckByCarId(carId));
		if((null == result)||(result.size() == 0)) {
			return null;
		}
		for(CarCheckDto carCheck : result) {
			CheckDisputeDto checkDispute = checkDisputeService.getByCheckId(carCheck.getId());
			if(null != checkDispute) {
				if(!checkDispute.getIsUserApproves()) {
					carCheck.setArtificialIntervention(BasicEnum.YES.getName());
				}else {
					carCheck.setArtificialIntervention(BasicEnum.NO.getName());
				}
			}else {
				carCheck.setArtificialIntervention(BasicEnum.NO.getName());
			}
		}
		return result;
	}

	@Override
	public List<CarCheckDto> getCheckByOrderCode(Long orderCode) {
		List<CarCheckDto> result = Convert.toCarCheckDto(checkService.getCheckByOrderCode(orderCode));
		if((null == result)||(result.size() == 0)){
			return null;
		}
		for(CarCheckDto checkDto : result) {
			CheckImageDto checkImageDto = checkImageService.getCheckPdfByCheckId(checkDto.getId());
			if(null != checkImageDto) {
				checkDto.setDomainPath(checkImageDto.getDomainPath());
				checkDto.setRelativePath(checkImageDto.getRelativePath());
			}
		}
		return result;
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
	public Boolean pdiCheckCar(PdiCheckModifyDto pdiCheckModifyDto)throws Exception {
		CheckDto checkDto = checkService.getById(pdiCheckModifyDto.getCheckId());
		if(null == checkDto) {
			throw new BizException(VehicleExceptionCodeEnum.NOT_EXIST.getCode(), VehicleExceptionCodeEnum.NOT_EXIST.getMessage());
		}
		/*
            检验单相关注释掉 2019-12-13 by 刘瑞丰
		int  modifyImage  =checkImageService.createPdiCheckImage(pdiCheckModifyDto.getCheckId(), pdiCheckModifyDto.getDomainPath(), CarCheckImageEnum.CHECK_SHEET.getValue());
		if(modifyImage < 0 ){
			throw new Exception("车辆PDI检验信息修改检验单失败");
		}*/

		int modifyCheck  =  checkService.pdiModifyCheckDto(pdiCheckModifyDto);
		if(modifyCheck < 0 ){
			throw new Exception("车辆检验信息修改检验信息质损费以及质损说明失败");
		}
		CarDto carDto = carService.getCarById(checkDto.getCarId());
		if(null== carDto) {
			throw new BizException(VehicleExceptionCodeEnum.CAR_NOT_EXIST.getCode(), VehicleExceptionCodeEnum.CAR_NOT_EXIST.getMessage());
		}
		int modifyCar = 0;
		if(carDto.getVehicleType() == CarsTypeEnum.NEW_CAR.getValue()) {  //新车

		    //增加新车检验数据
            CheckCreateDto newCarCheck = new CheckCreateDto();
            newCarCheck.setCarId(carDto.getId());
            newCarCheck.setCarType(CarsTypeEnum.NEW_CAR);
            newCarCheck.setOrderCode(checkDto.getOrderCode());
            newCarCheck.setReturnStoreId(checkDto.getReturnStoreId());
            newCarCheck.setType(CarCheckTypeEnum.NEW_CHECK);
            newCarCheck.setDealerId(checkDto.getDealerId());
            checkService.create(newCarCheck);

			modifyCar = carService.modifyStatusById(checkDto.getCarId(), CarsOperateStatusEnum.NOT_RENT);
		}else{
			modifyCar = carService.modifyStatusById(checkDto.getCarId(), CarsOperateStatusEnum.FOR_RENT);
		}
		if(modifyCar < 0 ){
			throw new Exception("车辆检验信息修改车辆信息失败");
		}

		//状态改为待用户确认
		boolean checkStatus = checkService.modifyCheckStatusAndOpName(checkDto.getId(), CarCheckStatusEnum.WAIT_CONFIRM.getValue(), pdiCheckModifyDto.getOpName()); //修改检验状态
		if (!checkStatus) {
			throw new Exception("pdi检验修改检验状态失败");
		}

		return true;
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
	public Boolean checkCar(CheckModifyDto checkModifyDto) throws Exception {
		CheckDto check = checkService.getById(checkModifyDto.getCheckId());
		if(null == check) {
			throw new BizException(VehicleExceptionCodeEnum.NOT_EXIST.getCode(), VehicleExceptionCodeEnum.NOT_EXIST.getMessage());
		}
		int modifyCheck  = checkService.modifyCheckDto(checkModifyDto.getCheckId(), checkModifyDto.getFacadeStatus(),
				checkModifyDto.getRemark(),checkModifyDto.getCheckPreparationModifyDto().getCarType(), checkModifyDto.getCarCheckModifyDto());
    	if(modifyCheck < 0 ){
			throw new Exception("车辆检验信息修改失败");
		}
		int modifyCheckImage =  checkImageService.createCheckImage(checkModifyDto.getCheckId(), checkModifyDto.getCheckImageModifyDto());
		if(modifyCheckImage < 0 ){
			throw new Exception("车辆检验图片信息修改失败");
		}
		int modifyCheckPreparation =  checkPreparationService.createCheckPreparation(checkModifyDto.getCheckId(),
				checkModifyDto.getCheckPreparationModifyDto());
		if(modifyCheckPreparation < 0 ){
			throw new Exception("车辆整备信息修改失败");
		}
		int modifyCarStatus = carService.modifyStatusAndVehicleTypeById(check.getCarId(), CarsOperateStatusEnum.FOR_RENT, CarsTypeEnum.getEnum(checkModifyDto.getCheckPreparationModifyDto().getCarType()));
		if(modifyCarStatus < 0 ){
			throw new Exception("车辆信息修改失败");
		}
		return true;
	}

	@Override
	public Paged<CarCheckDto> getPdiCarCheck(String licencePlate, String vin, Long orderCode, Integer returnStoreId,
			CarCheckStatusEnum carCheckStatusEnum, Integer pageSize, Integer pageNum,Integer dealerId) {
		Paged<CarCheckDto> dtoList = new Paged<CarCheckDto>();
		dtoList.setTab(getTabList());
		List<Integer> carIds = new ArrayList<>();
		CarDto catDto = new CarDto();
		if (licencePlate != null || vin != null) {
			// 查询车辆基础信息
			catDto = carService.getByVinLicencePlate(vin, licencePlate);
			if (catDto != null) {
				carIds.add(catDto.getId());
			} else {
				return dtoList;
			}
		}
		// 检验表基础信息
		Paged<CheckDto> list = checkService.getPdiCarsCheckListPage(carIds, orderCode, returnStoreId,
				carCheckStatusEnum, dealerId,pageSize, pageNum);
		if (list == null) {
			return dtoList;
		}
		List<CheckDto> checkDtoList = list.getList();
		if (checkDtoList == null) {
			return dtoList;
		}

		dtoList = Convert.toPagedCarCheckDto(list);
		// 遍历检验的基础信息
		for (CarCheckDto carCheckDto : dtoList.getList()) {
			CarDto carDto = carService.getCarById(carCheckDto.getCarId());
			carCheckDto.setCarId(carDto.getId());
			carCheckDto.setLicencePlate(carDto.getLicencePlate());
			carCheckDto.setVin(carDto.getVin());
			carCheckDto.setVehicleId(carDto.getVehicleId());
			carCheckDto.setCarTypeStr(CarsTypeEnum.getName(carCheckDto.getCarType()));
			carCheckDto.setStatusStr(CarCheckStatusEnum.getName(Integer.valueOf(carCheckDto.getStatus())));
		}
		dtoList.setTab(getTabList());
		return dtoList;
	}

	@Override
	public Boolean discussPdiCheck(DisPdiCheckModifyDto disPdiCheckModifyDto) {
		return null;
	}

	@Override
	public PdiCheckBizDto getCheckReport(Long orderCode) {
		List<CheckDto> checkDtoList = checkService.getCheckByOrderCode(orderCode);
		if(null == checkDtoList || checkDtoList.size() == 0) {
			return null;
		}
		CheckDisputeDto checkDisputeDto = checkDisputeService.getByCheckId(checkDtoList.get(0).getId());
		List<CheckImageDto> imageDto  =  checkImageService.getCheckImageByCheckId(checkDtoList.get(0).getId());
		CheckImageDto checkImageDto = new CheckImageDto();
		if(imageDto!=null && imageDto.size()>0){
			checkImageDto = imageDto.get(0);
		}
		return Convert.toPdiCheckVo(checkDtoList.get(0),checkDisputeDto,checkImageDto);
	}

	private List<TabDto> getTabList() {
		List<TabDto> tabList = new ArrayList<>();
		for (CarCheckTypeEnum statusEnum : CarCheckTypeEnum.values()) {
			int count = 0;
			if (statusEnum == CarCheckTypeEnum.NEW_CHECK) {
				count = checkService.getCount(statusEnum.getValue(), null);
			} else {
				count = checkService.getCount(statusEnum.getValue(), null);
			}
			TabDto tabDto = new TabDto();
			tabDto.setCount(count);
			tabDto.setName(statusEnum.getName());
			tabDto.setType(statusEnum.getValue());
			tabList.add(tabDto);
		}
		return tabList;
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
	public Boolean modifyReportConfirm(ReportModifyBizDto reportModifyBizDto) throws Exception {
		Boolean type = reportModifyBizDto.getType();
		Long orderCode = reportModifyBizDto.getOrderCode();
		Integer checkStatus=null;

		List<CheckDto> checkList = checkService.getCheckByOrderCode(orderCode);
		CheckDto checkDto = checkList.get(0);
		Integer checkId=checkDto.getId();

		if(type){
			checkStatus=CarCheckStatusEnum.ALREADY_CHECK.getValue();
		}else{
			checkStatus=CarCheckStatusEnum.WAIT_INTERVNTION.getValue();
		}
		Boolean modifyBoolean = checkService.modifyCheckStatus(checkId, checkStatus);
		if(!modifyBoolean){
			return false;
		}

		return checkDispute(checkId,reportModifyBizDto);
	}

	private Boolean checkDispute(Integer checkId,ReportModifyBizDto reportModifyBizDto) throws Exception{
		Boolean type = reportModifyBizDto.getType();
		String remark = reportModifyBizDto.getRemark();

		CheckDisputeDto checkDisputeDto = checkDisputeService.getByCheckId(checkId);
		if(null == checkDisputeDto){
			CheckDisputeCreateDto checkDisputeCreateDto=new CheckDisputeCreateDto();
			checkDisputeCreateDto.setCheckId(checkId);
			checkDisputeCreateDto.setReason(remark);
			checkDisputeCreateDto.setIsUserApproves(type);

			int result = checkDisputeService.createCheckDispute(checkDisputeCreateDto);
			if(result < 1){
				return false;
			}
		}else{
			CheckDisputeModifyDto checkDisputeModifyDto=new CheckDisputeModifyDto();
			checkDisputeModifyDto.setCheckId(checkId);
			checkDisputeModifyDto.setReason(remark);
			checkDisputeModifyDto.setIsUserApproves(type);

			return checkDisputeService.modifyCheckDispute(checkDisputeModifyDto);
		}

		return true;
	}

	/**
	 * 争议处理
	 * @param checkId
	 * @param discussLossFee
	 * @param remark
	 * @param operatorAccount
	 * @return
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
	public boolean modifyCheckDispute(Integer checkId, BigDecimal discussLossFee, String remark, String operatorAccount) throws Exception {

		int disputeNum = checkDisputeService.modifyCheckDispute(checkId, discussLossFee, remark, operatorAccount);
		if (disputeNum <= 0) {
			throw new BizException("争议处理失败");
		}

		boolean checkStatus = checkService.modifyCheckStatus(checkId, CarCheckStatusEnum.ALREADY_CHECK.getValue()); //修改检验状态
		if (!checkStatus) {
			throw new BizException("pdi检验修改检验状态失败");
		}

		return true;
	}
}
